// this file show the bad ref use.
use std::cell::RefCell;
use std::rc::Rc;

use std::collections::HashMap;

#[derive(Debug)]
pub enum PointType {
    Start,
    End,
    Path,
    Wall,
    Edge,
}
#[derive(Debug)]
pub struct PathPoint {
    pub point: (usize, usize),
    pub cell_type: PointType,
    pub top: Option<Rc<RefCell<PathPoint>>>,
    pub right: Option<Rc<RefCell<PathPoint>>>,
    pub bottom: Option<Rc<RefCell<PathPoint>>>,
    pub left: Option<Rc<RefCell<PathPoint>>>,
    pub valid_for_end: bool,
}

impl PathPoint {
    pub fn new(point: (usize, usize), content: char) -> Self {
        PathPoint {
            point: point,
            cell_type: match content {
                'S' => PointType::Start,
                'E' => PointType::End,
                '.' => PointType::Path,
                '#' => PointType::Wall,
                _ => PointType::Edge,
            },
            top: None,
            right: None,
            bottom: None,
            left: None,
            valid_for_end: true,
        }
    }
}

pub fn solve_maze(
    maze: Vec<Vec<char>>,
    start: (usize, usize),
    end: (usize, usize),
) -> Vec<(usize, usize)> {
    // Your code here
    let mut path: Vec<(usize, usize)> = Vec::new();
    // translate the maze to my struct vec

    let maze_deep = maze.len();
    let maze_width = maze[0].len();
    let max_deep_idx = maze_deep - 1;
    let max_width_idx = maze_width - 1;

    //let mut cell_vec: Vec<PathPoint> = Vec::new();
    let mut cell_hm: HashMap<(usize, usize), Rc<RefCell<PathPoint>>> = HashMap::new();

    // for row in maze {
    //     for column in row {
    //     }
    // }

    for y in 0..maze_deep {
        for x in 0..maze_width {
            let c = Rc::new(RefCell::new(PathPoint::new((x, y), maze[y][x])));
            cell_hm.insert((x, y), c);
            //cell_vec.push(c);
        }
    }

    for c in &cell_hm {
        match c.0 {
            // no left, lefe edge
            &(0_usize, y) => {
                // {
                // let mut tmp_cell: &RefCell<PathPoint> = c.1;
                // let tmp = cell_hm.get(&(tx + 1, ty)).unwrap();
                // tmp_cell.borrow_mut().right = Some(Rc::clone(tmp));
                // }
                // no left
                c.1.borrow_mut().right = Some(Rc::clone(cell_hm.get(&(0 + 1, y)).unwrap()));
                if y == 0 {
                    c.1.borrow_mut().top = None;
                    c.1.borrow_mut().bottom = Some(Rc::clone(cell_hm.get(&(0, y + 1)).unwrap()));
                } else if y == max_deep_idx {
                    c.1.borrow_mut().bottom = None;
                    c.1.borrow_mut().top = Some(Rc::clone(cell_hm.get(&(0, y - 1)).unwrap()));
                } else {
                    c.1.borrow_mut().top = Some(Rc::clone(cell_hm.get(&(0, y - 1)).unwrap()));
                    c.1.borrow_mut().bottom = Some(Rc::clone(cell_hm.get(&(0, y + 1)).unwrap()));
                }
            }
            // no top, top edge
            &(x, 0) => {
                // no top
                c.1.borrow_mut().bottom = Some(Rc::clone(cell_hm.get(&(x, 0 + 1)).unwrap()));
                if x == 0 {
                    c.1.borrow_mut().left = None;
                    c.1.borrow_mut().right = Some(Rc::clone(cell_hm.get(&(x + 1, 0)).unwrap()));
                } else if x == max_width_idx {
                    c.1.borrow_mut().right = None;
                    c.1.borrow_mut().left = Some(Rc::clone(cell_hm.get(&(x - 1, 0)).unwrap()));
                } else {
                    c.1.borrow_mut().left = Some(Rc::clone(cell_hm.get(&(x - 1, 0)).unwrap()));
                    c.1.borrow_mut().right = Some(Rc::clone(cell_hm.get(&(x + 1, 0)).unwrap()));
                }
            }
            // // no right, right edge
            // &(max_width_idx, y) => {
            //     // no right
            //     c.1.borrow_mut().right =
            //         Some(Rc::clone(cell_hm.get(&(max_width_idx - 1, y)).unwrap()));
            //     if y == 0 {
            //         c.1.borrow_mut().top = None;
            //         c.1.borrow_mut().bottom =
            //             Some(Rc::clone(cell_hm.get(&(max_width_idx, y + 1)).unwrap()));
            //     } else if y == max_deep_idx {
            //         c.1.borrow_mut().bottom = None;
            //         c.1.borrow_mut().top =
            //             Some(Rc::clone(cell_hm.get(&(max_width_idx, y - 1)).unwrap()));
            //     } else {
            //         c.1.borrow_mut().top =
            //             Some(Rc::clone(cell_hm.get(&(max_width_idx, y - 1)).unwrap()));
            //         c.1.borrow_mut().bottom =
            //             Some(Rc::clone(cell_hm.get(&(max_width_idx, y + 1)).unwrap()));
            //     }
            // }
            // // no bottom, bottom edge
            // &(x, max_deep_idx) => {
            //     // no bottom,
            //     c.1.borrow_mut().top =
            //         Some(Rc::clone(cell_hm.get(&(x, max_deep_idx - 1)).unwrap()));
            //     if x == 0 {
            //         c.1.borrow_mut().left = None;
            //         c.1.borrow_mut().right =
            //             Some(Rc::clone(cell_hm.get(&(x + 1, max_deep_idx)).unwrap()));
            //     } else if x == max_width_idx {
            //         c.1.borrow_mut().right = None;
            //         c.1.borrow_mut().left =
            //             Some(Rc::clone(cell_hm.get(&(x - 1, max_deep_idx)).unwrap()));
            //     } else {
            //         c.1.borrow_mut().left =
            //             Some(Rc::clone(cell_hm.get(&(x - 1, max_deep_idx)).unwrap()));
            //         c.1.borrow_mut().right =
            //             Some(Rc::clone(cell_hm.get(&(x + 1, max_deep_idx)).unwrap()));
            //     }
            // }
            // no corner, no edge
            &(x, y) => {
                // should set t,r,b,l
                c.1.borrow_mut().top = Some(Rc::clone(cell_hm.get(&(x, y - 1)).unwrap()));
                c.1.borrow_mut().left = Some(Rc::clone(cell_hm.get(&(x - 1, y)).unwrap()));
                if x != max_width_idx {
                    c.1.borrow_mut().right = Some(Rc::clone(cell_hm.get(&(x + 1, y)).unwrap()));
                }
                if y != max_deep_idx {
                    c.1.borrow_mut().bottom = Some(Rc::clone(cell_hm.get(&(x, y + 1)).unwrap()));
                }
            }
        };
    }

    // for ix in 0..1_usize {
    //     for iy in 0..1_usize {
    let tmp = cell_hm.get(&(0, 0)).unwrap();
    println!("{:?}", *tmp);
    //     }
    // }

    path.push(start);
    // check the cell's 4 direction, top, right, bottom, left

    path
}
